package com.oocl.server.analyzer.impl;

import java.security.KeyStore.ProtectionParameter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.omg.PortableInterceptor.USER_EXCEPTION;

import com.oocl.qq.protocol.Action;
import com.oocl.qq.protocol.Protocol;
import com.oocl.server.analyzer.ProtocolAnalyzer;
import com.oocl.server.dao.UserDao;
import com.oocl.server.dao.impl.UserDaoImpl;
import com.oocl.server.pojo.User;
import com.oocl.server.runnable.ChatRunnable;
import com.oocl.server.util.Logger;

public class ProtocolAnalyzerImpl implements ProtocolAnalyzer{
	private Map<String, ChatRunnable> threadMap;

	private ChatRunnable thisThread;

	private String curSocketName;
	
	private UserDao dao;

	public ProtocolAnalyzerImpl(Map<String, ChatRunnable> threadMap,
			ChatRunnable thisThread) {
		this.threadMap = threadMap;
		this.thisThread = thisThread;
		this.dao = new UserDaoImpl();
	}

	public void analyze(Protocol p) {
		if (p == null)
			return;
		
		switch (p.getAction()) {
		case Login:
			Logger.log("聊天服务器解析登录请求");
			dealWithLogin(p);
			break;

		case Logout:
			Logger.log("聊天服务器解析退出登录请求");
			// /退出登录
			dealWithLogout(p);
			break;

		case Shake:
			// / 震动屏幕
			if (p.getTo() == null || p.getTo().trim().length() == 0) {
				// / 群震
				dealWithShakeGroup(p);
			} else {
				// /单震
				Logger.log(this.curSocketName + "要震动的人： " + p.getTo());
				String toWhom = p.getTo().trim();
				if (this.threadMap.get(toWhom) != null) {
					Logger.log("找到+" + toWhom + "的Thread存在！");
					dealWithShakeAlone(p, this.threadMap.get(toWhom));
				}
			}
			break;

		case Chat:
			// 对话
			if (p.getTo() == null || p.getTo().trim().length() == 0) {
				// / 群聊
				Logger.log(this.curSocketName + "发起了群聊");
				dealWithChatGroup(p);
			} else {
				// / 单聊
				Logger.log(this.curSocketName + "发起了单聊");
				String toWhom = p.getTo().trim();
				if (this.threadMap.get(toWhom) != null) {
					Logger.log("找到+" + toWhom + "的Thread存在！");
					dealWithChatAlone(p, this.threadMap.get(toWhom));
				}
			}
			break;
		case Register:
			Logger.log("服务器解析注册请求");
			dealWithRegister(p);
			break;
		default:
			
			break;
		}
	}
	private void dealWithLogin(Protocol p) {
		// / 登录
		this.curSocketName = p.getFrom();
		
		String passWord = p.getMsg();
		String errorMsg = null;
		boolean logSuccess = false;
		//查看用户是否存在
		User user = dao.searchUser(this.curSocketName);
		
		//用户存在
		if(user != null ){
			if(!passWord.trim().equals(user.getPassWord().trim())){
				errorMsg = "用户" + this.curSocketName + "密码错误";
			} 
			else if(threadMap.get(this.curSocketName)!=null){
				errorMsg = "用户" +this.curSocketName + "已登录";
			}
			//密码正确，登录成功
			else {
				//上线了更新数据库
			    dao.updateUser(new User(this.curSocketName, user.getPassWord(), true));
   
				Logger.log("用户" + this.curSocketName + "登录成功");
				
				this.threadMap.put(this.curSocketName, this.thisThread);

				// /登录了，所以，服务端要给我自己返回一个所有在线用户的列表
				List<String> strList = sendUserList(this.curSocketName+"上线了。");
				
				// / 最后通知自己
				Logger.log("最后通知自己在线的用户信息");
				StringBuilder sb = new StringBuilder();
				strList.remove(this.curSocketName);
				sb.append(strList);
				System.out.println(sb.toString());
				Protocol resp = new Protocol(Action.Login, this.curSocketName);
				resp.setMsg(sb.toString());
				resp.setTime(p.getTime());
				this.thisThread.sendMsg(resp);
				
				logSuccess = true;
			}	
		} 
		// 登录失败
        if(!logSuccess){
			if(errorMsg==null)
			      errorMsg = errorMsg = "用户" +this.curSocketName + "未注册";;
			
			 Logger.log(errorMsg);
			 
			//将登录失败原因发回客户端
			Protocol resp = new Protocol(Action.Logout, null);
			resp.setMsg(errorMsg);
			resp.setTime(p.getTime());
			
			this.thisThread.sendMsg(resp);
		}
	}
	private void dealWithRegister(Protocol p){
		this.curSocketName = p.getFrom();
		User user = dao.searchUser(this.curSocketName);
		Protocol resp;
		Boolean regSuccess = false;
		String msg = null;
		String errMsg = null;
		
		//用户名不存在，向数据库中存入用户数据
		if(user == null){
			String passWord = p.getMsg();
			User newUser = new User(this.curSocketName, passWord, true);
			
		    if(dao.addUser(newUser) != 0){
		    	Logger.log("用户" + this.curSocketName + "注册成功");
		    	
		    	regSuccess = true;
				
				this.threadMap.put(this.curSocketName, this.thisThread);

				// /登录了，所以，服务端要给我自己返回一个所有在线用户的列表
				List<String> strList = sendUserList(this.curSocketName+"上线了。");
				
				// / 最后通知自己
				Logger.log("最后通知自己在线的用户信息");
				StringBuilder sb = new StringBuilder();
				strList.remove(this.curSocketName);
				sb.append(strList);
				System.out.println(sb.toString());
				resp = new Protocol(Action.Login, this.curSocketName);
				resp.setMsg(sb.toString());
				resp.setTime(p.getTime());
				
				this.thisThread.sendMsg(resp);
		    	
		    } else {
		    	msg = "用户" + this.curSocketName + "注册失败";
		    	errMsg = "用户" + this.curSocketName + "数据存入DB失败";
		    }
		} else {
			msg = "用户名" + this.curSocketName + "已存在";
			errMsg = msg;
		}
		
		//注册失败
		if(regSuccess == false){
			Logger.log(errMsg);
			
			resp = new Protocol(Action.Register, null);
			resp.setMsg(msg);
			
			resp.setTime(p.getTime());
			this.thisThread.sendMsg(resp);
		}
	}
 
    //单震
	private void dealWithShakeAlone(Protocol p, ChatRunnable requestThread) {
		Protocol resp = new Protocol(Action.Shake, this.curSocketName,
				p.getTo(), p.getMsg(), p.getTime());
		requestThread.sendMsg(resp);
	}
    /// 群震
	private void dealWithShakeGroup(Protocol p) {

		Set<String> keySet = threadMap.keySet();

		for (String name : keySet) {
			if (!name.equals(this.curSocketName)) {
				ChatRunnable targetThread = threadMap.get(name);
				targetThread
						.sendMsg(new Protocol(Action.Shake, this.curSocketName,
								p.getTo(), p.getMsg(), p.getTime()));
			}
		}
	}

	// / 群聊
	private void dealWithChatGroup(Protocol p) {

		Set<String> keySet = threadMap.keySet();

		for (String name : keySet) {
			if (!name.equals(this.curSocketName)) {
				Logger.log("用户 " + name + "将会收到消息");

				ChatRunnable targetThread = threadMap.get(name);
				targetThread.sendMsg(new Protocol(Action.Chat, this.curSocketName, null,
						p.getMsg(), p.getTime()));
			}
		}
	}

	// // 单聊
	private void dealWithChatAlone(Protocol p, ChatRunnable targetThread) {
		Protocol resp = new Protocol(Action.Chat, this.curSocketName,
				p.getTo(), p.getMsg(), p.getTime());
		targetThread.sendMsg(resp);
	}
	


	// / 退出登录
	public void dealWithLogout(Protocol p) {
		System.out.println("dealWithLogout(P)");
		// 删除用户
		threadMap.remove(this.curSocketName);

		
		//下线了更新数据库
	    User user = dao.searchUser(this.curSocketName);
	    if(user != null && user.isOnline() == true){
	    	dao.updateUser(new User(this.curSocketName, user.getPassWord(), false));
	    }

		///退出了，所以，服务端要给我自己返回一个所有在线用户的列表
		sendUserList(this.curSocketName+"下线了");
		
		Logger.log("用户 " + this.curSocketName + " 退出登录了");

		this.curSocketName = null;// /
	}

	// / 退出登录
	public void dealWithLogout() {
		System.out.println("dealWithLogout()");
		// /如果 curSocketName == null; 说明 用户已经退出了登录，下面代码不会执行
		if (this.curSocketName == null)
			return;

		//下线了更新数据库
	    User user = dao.searchUser(this.curSocketName);
	    if(user != null){
	    	dao.updateUser(new User(this.curSocketName, user.getPassWord(), false));
	    }
		
		Logger.log(this.curSocketName + "异常退出了");
		System.out.println(this.curSocketName + "异常退出了");

		// 删除用户
		threadMap.remove(this.curSocketName);

		///退出了，所以，服务端要给我自己返回一个所有在线用户的列表
		sendUserList(this.curSocketName+"下线了。");	
	}


	/// 发送在线用户信息列表
	public List<String> sendUserList(String msg){
		Set<Entry<String, ChatRunnable>> nameSet = threadMap.entrySet();
		Iterator<Entry<String, ChatRunnable>> it = nameSet.iterator();
		StringBuilder sb = new StringBuilder();
		List<String> strList = new ArrayList<String>();

		while (it.hasNext()) {
			Entry<String, ChatRunnable> item = it.next();
			strList.add(item.getKey());
		}
		// //通知所有在线用户，更新列表
		nameSet = threadMap.entrySet();
		it = nameSet.iterator();
		while (it.hasNext()) {
			Entry<String, ChatRunnable> item = it.next();
			ChatRunnable otherClient = item.getValue();
			sb = new StringBuilder();
			
			Logger.log("当前要通知的人： " + item.getKey());
			
			if (item.getKey().equals(this.curSocketName))
				continue;
			strList.remove(item.getKey());
			sb.append(strList);
			System.out.println(sb.toString());
			
			Protocol userList =  new Protocol(Action.List, sb.toString());

			userList.setMsg(msg);
			userList.setTime(System.currentTimeMillis());
			otherClient.sendMsg(userList);
			strList.add(item.getKey());
		}
		return strList;
	}
}
